﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Walson.Form
{
    public partial class FlightInstrument
    {
        [ToolboxItem(false)]
        public partial class PitchAndBank : UserControl
        {
            private Bitmap _MJpegStream;

            private float _Bank;
            public double Bank
            {
                get
                {
                    return _Bank;
                }
                set
                {
                    while (value < 0)
                        value += 360;
                    _Bank = (float)value % 360;
                    this.Invalidate();
                }
            }

            private float _Pitch;
            public double Pitch
            {
                get
                {
                    return _Pitch;
                }
                set
                {
                    while (value < -360)
                        value += 360;
                    while (value > 360)
                        value -= 360;
                    _Pitch = (float)value % 360;
                    this.Invalidate();
                }
            }

            private float _Altitude;
            public double Altitude
            {
                get
                {
                    return _Altitude;
                }
                set
                {
                    _Altitude = (float)value;
                    this.Invalidate();
                }
            }

            private float _AirSpeed;
            public double AirSpeed
            {
                get
                {
                    return _AirSpeed;
                }
                set
                {
                    _AirSpeed = (float)value;
                    this.Invalidate();
                }
            }

            private float _BankLimit;
            public double BankLimit
            {
                get
                {
                    return _BankLimit;
                }
                set
                {
                    while (value > 360)
                        value -= 360;
                    while (value < 0)
                        value += 360;

                    if (BankLimit != value)
                    {
                        _BankLimit = (float)value % 360;
                        this.Invalidate();
                    }

                }
            }

            private bool _OverSpeed;
            public bool OverSpeed
            {
                get
                {
                    return _OverSpeed;
                }
                set
                {
                    if (value != _OverSpeed)
                    {
                        _OverSpeed = value;
                        this.Invalidate();
                    }
                }
            }

            private bool _Stall;
            public bool Stall
            {
                get
                {
                    return _Stall;
                }
                set
                {
                    if (value != _Stall)
                    {
                        _Stall = value;
                        this.Invalidate();
                    }
                }
            }

            private string _MJpegUrl;
            public string MJpegUrl
            {
                get
                {
                    return _MJpegUrl;
                }
                set
                {
                    _MJpegUrl = value;
                    this.Invalidate();
                }
            }

            private bool _ShowMJpegStream;
            public bool ShowMJpegStream
            {
                get
                {
                    return _ShowMJpegStream;
                }
                set
                {
                    _ShowMJpegStream = value;
                    this.Invalidate();
                }
            }

            private float _HeightFromGround;
            /// <summary>
            /// 距离地面的高度
            /// </summary>
            public double HeightFromGround
            {
                get
                {
                    return _HeightFromGround;
                }
                set
                {
                    _HeightFromGround =(float) value;
                    this.Invalidate();
                }
            }

            private int _DangerHeight = 300;
            public int DangerHeight
            {
                get
                {
                    return _DangerHeight;
                }
                set
                {
                    _DangerHeight = value;
                    this.Invalidate();
                }
            }

            private int _SleepTime;
            private int _FrameRate;
            public int FrameRate
            {
                get
                {
                    return _FrameRate;
                }
                set
                {
                    _FrameRate = value;
                    _SleepTime = 1000 / _FrameRate;
                }
            }

            public Bitmap Image
            {
                get;
                private set;
            }

            public PitchAndBank()
            {
                InitializeComponent();
                _WhitePen = new Pen(Brushes.White, 2);
                _BankLimit = 45;
                _FrameRate = 15;
                _MJpegUrl = string.Empty;
                _ShowMJpegStream = false;

                this.Image = new Bitmap(1, 1);
            }

       

            private void thdGetMjpegStream()
            {
                byte[] buffer = new byte[100];
                int read, total = 0;
                MemoryStream ms = new MemoryStream();
                while (_ShowMJpegStream == true)
                {
                    read = 0;
                    total = 0;
                    Thread.Sleep(_SleepTime);
                    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_MJpegUrl);
                    WebResponse resp = req.GetResponse();
                    Stream stream = resp.GetResponseStream();

                    while (true)
                    {
                        read = stream.Read(buffer, 0, 100);
                        if (read != 0)
                        {
                            total += read;
                            ms.Write(buffer, 0, read);
                        }
                        else
                            break;
                    }

                    //                 while ((read = stream.Read(buffer, total, 100)) != 0)
                    //                 {
                    //                     total += read;
                    //                 }
                    if (total != 0)
                    {
                        //Bitmap bmp1 = (Bitmap)Bitmap.FromStream(new MemoryStream(buffer, 0, total));
                        _MJpegStream = (Bitmap)Bitmap.FromStream(ms);
                    }
                }
            }

            private Pen _WhitePen;
            protected override void OnPaint(PaintEventArgs e)
            {
                using (Bitmap bmp = new Bitmap(this.Width, this.Height))
                {
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        PointF[] polygon;

                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                        if (_ShowMJpegStream == true)
                        {
                            if (_MJpegStream != null)
                                g.DrawImage(_MJpegStream, 0, 0);
                        }

                        // 设置平移
                        g.TranslateTransform(this.Width / 2f, this.Height / 2f);

                        // 设置旋转
                        g.RotateTransform(_Bank);
                        g.TranslateTransform(0, _Pitch * 6f);

                        if (_ShowMJpegStream == false)
                        {
                            g.Clear(Color.FromArgb(99, 57, 24));

                            // 绘制天和地
                            polygon = new PointF[4];
                            polygon[0] = new PointF(-Width * 5f, 0f);
                            polygon[1] = new PointF(Width * 5f, 0f);
                            polygon[2] = new PointF(Width * 5f, -Height * 5f);
                            polygon[3] = new PointF(-Width * 5f, -Height * 5f);
                            g.FillPolygon(new SolidBrush(Color.FromArgb(41, 156, 239)), polygon);
                            // 天地分界线
                            g.DrawLine(_WhitePen, -Width * 5f, 0, Width * 5f, 0);
                        }

                        // 绘制俯仰角度刻度线
                        for (int i = 0; i <= 36; i++)
                        {

                            if (i % 4 == 0)
                            {
                                if ((i * 15f > -this.Height / 2f + 50 - _Pitch * 6))
                                {
                                    g.DrawLine(_WhitePen, -40, i * 15f, 40, i * 15f);
                                    g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 12f, FontStyle.Bold), Brushes.White, 46, i * 15f - 10);
                                    g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 12f, FontStyle.Bold), Brushes.White, -71, i * 15f - 10);
                                }
                                if (!(-i * 15f < -this.Height / 2f + 50 - _Pitch * 6))
                                {
                                    g.DrawLine(_WhitePen, -40, -i * 15f, 40, -i * 15f);
                                    g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 12f, FontStyle.Bold), Brushes.White, 46, -i * 15f - 10);
                                    g.DrawString((i / 4 * 10).ToString(), new Font("Times NewRoman", 12f, FontStyle.Bold), Brushes.White, -71, -i * 15f - 10);
                                }
                            }
                            else if (i % 2 == 0)
                            {
                                if ((i * 15f > -this.Height / 2f + 50 - _Pitch * 6))
                                    g.DrawLine(_WhitePen, -20, i * 15f, 20, i * 15f);
                                if (!(-i * 15f < -this.Height / 2f + 50 - _Pitch * 6))
                                    g.DrawLine(_WhitePen, -20, -i * 15f, 20, -i * 15f);
                            }
                            else
                            {
                                if ((i * 15f > -this.Height / 2f + 50 - _Pitch * 6))
                                    g.DrawLine(_WhitePen, -10, i * 15f, 10, i * 15f);
                                if (!(-i * 15f < -this.Height / 2f + 50 - _Pitch * 6))
                                    g.DrawLine(_WhitePen, -10, -i * 15f, 10, -i * 15f);
                            }
                        }

                        // 绘制三角形
                        g.ResetTransform();
                        g.TranslateTransform(this.Width / 2f, this.Height / 2f);
                        g.RotateTransform(_Bank);
                        PointF[] triangle = new PointF[4];
                        triangle[0] = new PointF(0, 30 - this.Height / 2);
                        triangle[1] = new PointF(-10, 45.77f - this.Height / 2);
                        triangle[2] = new PointF(10, 45.77f - this.Height / 2);
                        triangle[3] = new PointF(0, 30 - this.Height / 2);
                        g.DrawLines(_WhitePen, triangle);
                        if (_Bank < _BankLimit || _Bank > 360 - _BankLimit)
                            g.FillPolygon(Brushes.Yellow, triangle);
                        else
                            g.FillPolygon(Brushes.Red, triangle);

                        // 恢复平移和旋转
                        g.ResetTransform();
                        //g.DrawString(_Pitch.ToString(), this.Font, Brushes.Black, 10, 10);
                        // 设置平移
                        g.TranslateTransform(this.Width / 2f, this.Height / 2f);
                        // 中间的小方块
                        g.DrawRectangle(_WhitePen, -4, 0, 8, 8);

                        // 绘制水平指示
                        PointF[] centerIndicator = new PointF[7];
                        centerIndicator[0] = new PointF(-25, 0);
                        centerIndicator[1] = new PointF(-90, 0);
                        centerIndicator[2] = new PointF(-90, 7);
                        centerIndicator[3] = new PointF(-32, 7);
                        centerIndicator[4] = new PointF(-32, 20);
                        centerIndicator[5] = new PointF(-25, 20);
                        centerIndicator[6] = new PointF(-25, 0);
                        g.FillPolygon(Brushes.Black, centerIndicator);
                        g.DrawLines(_WhitePen, centerIndicator);

                        centerIndicator[0] = new PointF(25, 0);
                        centerIndicator[1] = new PointF(90, 0);
                        centerIndicator[2] = new PointF(90, 7);
                        centerIndicator[3] = new PointF(32, 7);
                        centerIndicator[4] = new PointF(32, 20);
                        centerIndicator[5] = new PointF(25, 20);
                        centerIndicator[6] = new PointF(25, 0);
                        g.FillPolygon(Brushes.Black, centerIndicator);
                        g.DrawLines(_WhitePen, centerIndicator);



                        // 绘制顶上的量角器
                        double r1 = Math.Min(this.Width, this.Height) / 2, r2 = r1 - 20;
                        double x1, y1, x2, y2;
                        for (int i = -180; i <= 0; i += 10)
                        {
                            if (i % 30 == 0)
                            {
                                x1 = r1 * Math.Cos(Math.PI * i / 180.0);
                                y1 = r1 * Math.Sin(Math.PI * i / 180.0);
                                x2 = r2 * Math.Cos(Math.PI * i / 180.0);
                                y2 = r2 * Math.Sin(Math.PI * i / 180.0);
                            }
                            else
                            {
                                x1 = (r1 - 10) * Math.Cos(Math.PI * i / 180.0);
                                y1 = (r1 - 10) * Math.Sin(Math.PI * i / 180.0);
                                x2 = r2 * Math.Cos(Math.PI * i / 180.0);
                                y2 = r2 * Math.Sin(Math.PI * i / 180.0);
                            }
                            g.DrawLine(_WhitePen, (float)x1, (float)y1, (float)x2, (float)y2);
                        }

                        g.ResetTransform();
                        System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
                        if (_OverSpeed)
                        {
                            //                         path.AddString("超速", new FontFamily("宋体"),2 , 20, new Point(20, 20), StringFormat.GenericDefault);
                            //                         g.FillPath(Brushes.Red,path);
                            //                         g.DrawPath(Pens.White,path);
                            Point txtPoint = new Point(12, 12);
                            Font font = new Font("宋体", 12, FontStyle.Bold);
                            string str = "超速";
                            // txtPoint是绘制文字的定位点
                            txtPoint.Offset(-1, 0);  // 绘制左背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(2, 0);  // 绘制右背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(-1, -1);  // 绘制下背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(0, 2);  // 绘制上背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(0, -1);  // 定位点归位
                            g.DrawString(str, font, Brushes.Red, txtPoint);
                        }
                        if (_Stall)
                        {
                            Point txtPoint = new Point(12, 12);
                            Font font = new Font("宋体", 12, FontStyle.Bold);
                            string str = "失速";
                            // txtPoint是绘制文字的定位点
                            txtPoint.Offset(-1, 0);  // 绘制左背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(2, 0);  // 绘制右背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(-1, -1);  // 绘制下背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(0, 2);  // 绘制上背景文字
                            g.DrawString(str, font, Brushes.White, txtPoint);
                            txtPoint.Offset(0, -1);  // 定位点归位
                            g.DrawString(str, font, Brushes.Red, txtPoint);
                        }
                        // 高度小于危险高度时开始提示
                        if (_HeightFromGround <= _DangerHeight)
                        {
                            string str = _HeightFromGround.ToString("f0")/* + " cm"*/;
                            Font font = new Font("宋体", 9, FontStyle.Regular);
                            SizeF size = g.MeasureString(str, font);
                            Rectangle rect0 ;
                            if (size.Width < 40)
                                rect0 = new Rectangle((int)(this.Width / 2 - 20), (int)(this.Height - 25), 40, 20);
                            else
                                rect0 = new Rectangle((int)(this.Width / 2 - size.Width / 2 - 5), (int)(this.Height - 25), (int)(size.Width + 10), 20);
                            //Point strLocation = new Point((int)(this.Width / 2 - size.Width / 2), (int)(this.Height - 25 + size.Height / 2));
                            PointF strLocation = new PointF((this.Width / 2 - size.Width / 2+1), (this.Height - 13f - size.Height / 2));
                            g.FillRectangle(new SolidBrush(Color.FromArgb(16, 16, 49)), rect0);
                            g.DrawRectangle(Pens.White, rect0);
                            g.DrawString(str, font, Brushes.White, strLocation);
                        }
                    }
                    this.Image = bmp;
                    e.Graphics.DrawImage(bmp, 0, 0);
                }

                // 绘制圆角控件
                Rectangle rect = new Rectangle(0, 0, base.Width, base.Height);
                int radius = 50;
                System.Drawing.Drawing2D.GraphicsPath roundRect = new System.Drawing.Drawing2D.GraphicsPath();
                //顶端 
                roundRect.AddLine(rect.Left + radius - 1, rect.Top - 1, rect.Right - radius, rect.Top - 1);
                //右上角 
                roundRect.AddArc(rect.Right - radius, rect.Top - 1, radius, radius, 270, 90);
                //右边 
                roundRect.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
                //右下角
                roundRect.AddArc(rect.Right - radius, rect.Bottom - radius, radius, radius, 0, 90);
                //底边 
                roundRect.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
                //左下角 
                roundRect.AddArc(rect.Left - 1, rect.Bottom - radius, radius, radius, 90, 90);
                //左边 
                roundRect.AddLine(rect.Left - 1, rect.Top + radius, rect.Left - 1, rect.Bottom - radius);
                //左上角 
                roundRect.AddArc(rect.Left - 1, rect.Top - 1, radius, radius, 180, 90);
                this.Region = new Region(roundRect);
                base.OnPaint(e);
            }

            protected override void OnPaintBackground(PaintEventArgs e)
            {
                base.OnPaintBackground(e);
            }

            private void PrimaryFlightDisplay_Resize(object sender, EventArgs e)
            {
                //this.Height = this.Width;
                //this.Invalidate();
            }
        }
    }
}